<template>
  <div
    class="vui__scrollbar"
    ref="ref__box"
    @mouseenter="handleMouseEnter"
    @mouseleave="handleMouseLeave"
    v-resize="handleResize"
  >
    <div
      :class="['vscroll__wrap', { native: native }]"
      ref="ref__wrap"
      @scroll="handleScroll"
    >
      <div class="vscroll__view" v-resize="handleResize">
        <slot />
      </div>
    </div>
    <div
      :class="['vscroll__bar vertical']"
      @mousedown="handleClickTrack($event, 0)"
      :style="{
        width: Number(size) >= 0 ? Number(size) + 'px' : 'auto',
        zIndex: Number(zIndex) >= 0 ? Number(zIndex) : 'auto',
      }"
    >
      <div
        class="vscroll__thumb"
        ref="ref__barY"
        :style="{ background: color, height: barHeight + 'px' }"
        @mousedown="handleDragThumb($event, 0)"
      ></div>
    </div>
    <div
      :class="['vscroll__bar horizontal']"
      @mousedown="handleClickTrack($event, 1)"
      :style="{
        height: Number(size) >= 0 ? Number(size) + 'px' : 'auto',
        zIndex: Number(zIndex) >= 0 ? parseInt(zIndex + '') : 'auto',
      }"
    >
      <div
        class="vscroll__thumb"
        ref="ref__barX"
        :style="{ background: color, width: barWidth + 'px' }"
        @mousedown="handleDragThumb($event, 1)"
      ></div>
    </div>
  </div>
</template>

<script lang="ts">
import { defineComponent, onMounted, ref, reactive, toRefs, nextTick } from "vue";
export default defineComponent({
  name: "v3-scroll",
  props: {
    // 是否显示原生滚动条
    native: Boolean,
    // 是否自动隐藏滚动条
    autohide: Boolean,
    // 滚动条尺寸
    size: { type: [Number, String], default: "" },
    // 滚动条颜色
    color: String,
    // 滚动条层级
    zIndex: String,
  },
  // 监听DOM尺寸变化
  directives: {
    resize: {
      beforeMount: function (el, binding) {
        let width = "",
          height = "";
        function get() {
          const elStyle = el.currentStyle
            ? el.currentStyle
            : window.document.defaultView?.getComputedStyle(el, null);
          if (width !== elStyle.width || height !== elStyle.height) {
            binding.value({ width, height });
          }
          width = elStyle.width;
          height = elStyle.height;
        }
        el.__vueReize__ = setInterval(get, 16);
      },
      unmounted: function (el) {
        clearInterval(el.__vueReize__);
      },
    },
  },
  setup(props, context) {
    const ref__box = ref<HTMLDivElement | null>(null);
    const ref__wrap = ref<HTMLDivElement | null>(null);
    const ref__barX = ref<HTMLDivElement | null>(null);
    const ref__barY = ref<HTMLDivElement | null>(null);

    const data = reactive({
      barWidth: 0, // 滚动条宽度
      barHeight: 0, // 滚动条高度
      ratioX: 1, // 滚动条水平偏移率
      ratioY: 1, // 滚动条垂直偏移率
      isTaped: false, // 鼠标光标是否按住滚动条
      isHover: false, // 鼠标光标是否悬停在滚动区
      isShow: !props.autohide, // 是否显示滚动条
    });

    // 更新滚动区
    const updated = () => {
      if (props.native) return;
      const elBox = ref__box.value;
      const elWrap = ref__wrap.value;
      const elBarX = ref__barX.value;
      const elBarY = ref__barY.value;

      // let barSize = domUtils.getScrollBarSize();
      if (!(elBox && elWrap && elBarX && elBarY)) return;
      // 垂直滚动条
      if (elWrap.scrollHeight > elWrap.offsetHeight) {
        data.barHeight = elBox.offsetHeight ** 2 / elWrap.scrollHeight;
        data.ratioY =
          (elWrap.scrollHeight - elBox.offsetHeight) /
          (elBox.offsetHeight - data.barHeight);
        elBarY.style.transform = `translateY(${elWrap.scrollTop / data.ratioY}px)`;
        // 隐藏系统滚动条
        // if (barSize) {
        //   elWrap.style.marginRight = -barSize + "px";
        // }
      } else {
        data.barHeight = 0;
        elBarY.style.transform = "";
        elWrap.style.marginRight = "";
      }

      // 水平滚动条
      // ...
    };

    // 滚动区元素/DOM尺寸改变
    const handleResize = () => {
      // 执行更新操作
    };

    const handleMouseEnter = () => {};
    const handleMouseLeave = () => {};

    const handleDragThumb = (e: any, num: number) => {};
    const handleClickTrack = (e: any, num: number) => {};

    // ...

    return {
      ...toRefs(data),
      ref__box,
      ref__wrap,
      ref__barX,
      ref__barY,

      handleMouseEnter,
      handleMouseLeave,
      handleDragThumb,
      handleClickTrack,
      updated,
    };
  },
});
</script>

<style></style>
